package org.feng.config;

import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiPredicate;

/**
 * mysql 数据库连接配置，需要在Nacos中进行配置信息，写法2<br>
 * <pre>
 * dynamic:
 *   mysql:
 *     map:
 *       master:
 *         - merchantKey=master
 *         - host=127.0.0.1
 *         - port=3306
 *         - username=root
 *         - password=123456
 *         - database=dynamic_master1
 *         - connectTimeout=30
 *       slave:
 *         - merchantKey=slave
 *         - host=127.0.0.1
 *         - port=3306
 *         - username=root
 *         - password=123456
 *         - database=dynamic_slave1
 *         - connectTimeout=30
 * </pre>
 *
 * @version V1.0
 * @author: fengjinsong
 * @date: 2022年06月15日 15时17分
 */
@Slf4j
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = MysqlDatasourcePropertiesV2.PREFIX)
public class MysqlDatasourcePropertiesV2 {
    /**
     * 前缀
     */
    public static final String PREFIX = "dynamic.mysql";

    private Map<String, Set<String>> map;

    private static final String MERCHANT_KEY_PREFIX = "merchantKey";
    private static final String HOST_PREFIX = "host";
    private static final String PORT_PREFIX = "port";
    private static final String USERNAME_PREFIX = "username";
    private static final String PASSWORD_PREFIX = "password";
    private static final String DATABASE_PREFIX = "database";
    private static final String CONNECT_TIMEOUT_PREFIX = "connectTimeout";
    private static final String EQUALS = "=";

    @Getter
    private final List<Property> PROPERTY_LIST = new ArrayList<>();

    @PostConstruct
    private void init() {
        map.forEach((k, v) -> {
            final Property property = setToProperty(v);
            PROPERTY_LIST.add(property);
        });
    }

    private BiPredicate<String, String> isDbProperty = String::startsWith;

    private boolean setDbProperty(BiPredicate<String, String> isDbProperty, String prefix, Property result, String configProperty) {
        try {
            if (isDbProperty.test(configProperty, prefix)) {
                Class<Property> propertyClass = Property.class;
                Field field = propertyClass.getDeclaredField(prefix);
                field.setAccessible(true);
                if (field.getType().equals(Integer.class)) {
                    field.set(result, Integer.parseInt(configProperty.replaceFirst(prefix + EQUALS, "")));
                    return true;
                }
                field.set(result, configProperty.replaceFirst(prefix + EQUALS, ""));
                return true;
            }
        } catch (Exception e) {
            log.error("设置数据源属性时出错", e);
        }
        return false;
    }


    private Property setToProperty(Set<String> setProperty) {
        Property result = new Property();
        String[] prefixArr = {MERCHANT_KEY_PREFIX, HOST_PREFIX, PORT_PREFIX, USERNAME_PREFIX, PASSWORD_PREFIX, DATABASE_PREFIX, CONNECT_TIMEOUT_PREFIX};
        for (String property : setProperty) {
            for (String prefix : prefixArr) {
                if (setDbProperty(isDbProperty, prefix, result, property)) {
                    break;
                }
            }
        }
        return result;
    }
}
